# 文件上传

# 第一种:form 表单上传

    <form action='/ajax/upload' enctype="multipart/form-data" type='post' target='uploader'>
      <input type='file'>
      <input type='hidden' name='userid' value='123'>
      <input type='hidden' name='username' value='abc'>
      <input type='submit' value='Submit'>
    </form>
    <iframe id='uploader'></iframe>

小技巧:为 form 设置 target='xxx',xxx 与空 iframe 的id一致,可以避免表单提交后刷新页面。

# 第二种:FormData + ajax 上传

    <input type='file' id='file'>
    <input type='button' onclick='handleSubmit()'>

    function handleSubmit() {
        const file = document.getElementById('file').files[0]   // blob 数据,即二进制大数据
        const formData = new FormData()
        formData.append('userid', '123')
        formData.append('file', file)
        // ajax post 发送
        const xhr = new XMLHttpRequest()
      xhr.open('POST', '/ajax/upload')
      xhr.onload = function () {
        if (xhr.status === 200) {
          console.log('上传成功');
        } else {
          console.log('出错了');
        }
      };
      xhr.send(formData)
    }

# 第三种:利用 H5 的 FileReader 上传

    <div id='preview'></div>
    <input type='file' id='file'>
    <input type='button' onclick='handleSubmit()'>

    function handleSubmit() {
        const file = document.getElementById('file').files[0]   // blob 数据,即二进制大数据
        const reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = function(e) {
            const data = e.target.result    // base64 数据,假如该文件为图片,此时拿到上传的数据后就可以做预览功能了
            // 图片预览
            document.getElementById('preview').
            // ajax post 发送
            const xhr = new XMLHttpRequest()
          xhr.open('POST', '/ajax/upload')
          xhr.onload = function () {
            if (xhr.status === 200) {
              console.log('上传成功');
            } else {
              console.log('出错了');
            }
          };
          xhr.send(data)
        }
    }

上传图片是可能遇到的问题:

  1. 格式转化

  2. 图片压缩

     // 思路:利用 canvas 实现压缩  file(blob) -> base64 -> image -> canvas压缩 -> base64
    
     /**
      * fileId - 上传文件的元素id
      * rate - 压缩率 小于1-压缩 大于1-放大
     **/
     async function compressPic(fileId, rate) {
         // 1.获取 blob
         const file = document.getElementById(fileId).files[0]   // blob-二进制大数据
         // 2.blob 转 base64
         const bs64 = await blob2Base(file).then((e) => {
             return e.target.result    // base64
         })
         console.log(bs64)           
         // 3.base64 转 image
         const img = base2Img(bs64)
         // 4.image 转 canvas
         const canvas = await img2Canvas(img).then(() => {
             const canvas = document.createElement('canvas')
             canvas.width = img.width
             canvas.height = img.height 
             return canvas
         })
         // 5.压缩并得到压缩后的base64
         const newBs64 = doCompress(canvas, img, rate)
         return newBs64
     }
    
     function blob2Base(file) {
         return new Promise((resolve, reject) => {
             const reader = new FileReader()
             reader.readAsDataURL(file)
             reader.onload = (e) => resolve(e)
             reader.onerror = () => reject('加载失败')
         })
     }
    
     function base2Img(bs64) {
         const img = new Image()
         img.crossOrigin = ''
         img.src = bs64
         return img
         
     }
    
     function img2Canvas(img) {
         return new Promise((resolve, reject) => {  
             img.onload = () => resolve()
             img.onerror = () => reject('加载失败')
         })
     }
    
     function doCompress(canvas, img, rate) {
         const ctx = canvas.getContext('2d')
         const canvaswidth = img.width * rate
         const canvasheight = img.height * rate
         canvas.width = canvaswidth
         canvas.height = canvasheight
         ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvaswidth, canvasheight)
         const ext = img.src.substring(img.src.lastIndexOf('.') + 1).toLowerCase()
         const dataURL = canvas.toDataURL('image/' + ext)
         return dataURL
     }
    
     async function getData() {
         const data = await compressPic('upload', 0.1)
         console.log(data)
     }
    
     document.getElementById('upload').addEventListener('change', function() {
         getData()
     })
    
最后更新时间: 6/17/2021, 8:13:14 PM